

package ru.samgtu.wst.util.swing;

import java.util.logging.Handler;
import java.util.logging.LogRecord;
import java.util.logging.ErrorManager;

import javax.swing.text.Document;
import javax.swing.text.PlainDocument;
import javax.swing.text.BadLocationException;


public class DocumentHandler extends Handler {

	private PlainDocument _doc;
	private int _max = Integer.MAX_VALUE;

	/** Creates a new instance of DocumentHandler */
	public DocumentHandler() {
		this(Integer.MAX_VALUE);
	}

	public DocumentHandler(int limit) {
		_max = limit;
		_doc = new PlainDocument();
	}

	public Document getDocument() {
		return _doc;
	}

	@Override
	public void close() {
	}

	@Override
	public void flush() {
	}

	@Override
	public void publish(LogRecord record) {
		if (!isLoggable(record)) {
			return;
		}
		final String msg;
		try {
			msg = getFormatter().format(record);
		} catch (Exception ex) {
			// We don't want to throw an exception here, but we
			// report the exception to any registered ErrorManager.
			reportError(null, ex, ErrorManager.FORMAT_FAILURE);
			return;
		}
		try {
			makeSpace(msg.length());
			_doc.insertString(_doc.getLength(), msg, null);
			// cr++;
		} catch (Exception ex) {
			// We don't want to throw an exception here, but we
			// report the exception to any registered ErrorManager.
			reportError(null, ex, ErrorManager.WRITE_FAILURE);
		}
	}

	private void makeSpace(int count) {
		int length = _doc.getLength();
		if (length + count < _max) {
			return;
		}
		try {
			if (count > _max) {
				_doc.remove(0, length);
			} else {
				int min = length + count - _max;
				String remove = _doc.getText(min, Math.min(500, length - min));
				int cr = remove.indexOf("\n");
				if (cr < 0) {
					min = min + remove.length();
				} else {
					min = Math.min(min + cr + 1, length);
				}
				_doc.remove(0, min);
			}
		} catch (BadLocationException ble) {
			System.err.println("BLE! " + ble);
		}
	}

}
